package validator

import (
	"bytes"
	"encoding/json"
	"github.com/wanchain/go-mpc/common"
	"github.com/wanchain/go-mpc/common/hexutil"
	"github.com/wanchain/go-mpc/log"
	mpcprotocol "github.com/wanchain/go-mpc/storeman/storemanmpc/protocol"
	"time"
)

func BytesCombine(pBytes ...[]byte) []byte {
	return bytes.Join(pBytes, []byte(""))
}

func genDBKey(txData mpcprotocol.SendEcData, keyType string)(approvedKey []byte){
	keyData:= BytesCombine(txData.PKBytes,txData.TxHash,[]byte(txData.ChainType))
	approvedKey = buildKeyFromBytes(keyData, keyType)
	return approvedKey
}

func AddApprovingDotTran(txByteData []byte) error {
	var txData mpcprotocol.SendEcData
	json.Unmarshal(txByteData, &txData)
	approvedKey := genDBKey(txData, mpcprotocol.MpcApprovedDot)
	approvingKey := genDBKey(txData, mpcprotocol.MpcApprovingDot)
	approvingKeysKey := []byte(mpcprotocol.MpcApprovingKeysDot)

	txData.RcvTimeStamp = time.Now()

	value, err := json.Marshal(&txData)
	if err != nil {
		log.SyslogErr("AddApprovingDotTran, json.Marshal fail", "err", err.Error())
		return err
	}
	log.SyslogInfo("AddApprovingDotTran",
		"@@@@@approvingKey@@@@@", hexutil.Encode(approvingKey),
		"@@@@@approvedKey@@@@@", hexutil.Encode(approvedKey),
		"value", (&txData).String())
	return addApproving(approvedKey, approvingKey, approvingKeysKey, value)
}

func ValidateDotTx(txByteData []byte) bool {

	log.SyslogInfo("ValidateDotTx, begin", "txInfo", string(txByteData))

	var txData mpcprotocol.SendEcData
	json.Unmarshal(txByteData, &txData)

	keyApproved := genDBKey(txData, mpcprotocol.MpcApprovedDot)

	log.SyslogInfo("ValidateDotTx", "#####keyWithoutTxin#####", common.ToHex(keyApproved))

	key, err := waitKeyFromDB([][]byte{keyApproved})
	if err != nil {
		log.SyslogErr("ValidateDotTx, check has fail", ">>>>>>key", common.ToHex(key), "err", err.Error(), "txInfo", string(txByteData))
		return false
	} else {
		log.SyslogInfo("ValidateDotTx successfully, key is got", ">>>>>>key", common.ToHex(key), "txInfo", string(txByteData))
		return true
	}
}

func GetDotTransForApprove(duration time.Duration) ([]mpcprotocol.SendEcData, error) {
	log.SyslogInfo("GetDotTransForApprove, begin")

	approvingBytes, _ := getForApprove([]byte(mpcprotocol.MpcApprovingKeysDot))
	var approvingData []mpcprotocol.SendEcData

	for i := 0; i < len(approvingBytes); i++ {

		var approvingTemp mpcprotocol.SendEcData
		err := json.Unmarshal(approvingBytes[i], &approvingTemp)
		if err != nil {
			log.SyslogErr("GetDataForApprove, Unmarshal approvingTemp", "err", err.Error())
			//return nil, err
			continue
		}

		if approvingTemp.RcvTimeStamp.Add(duration).After(time.Now()) {
			approvingData = append(approvingData, approvingTemp)
		}
	}
	return approvingData, nil
}

func ApproveDotTrans(data []mpcprotocol.SendEcData) []error {

	retResult := make([]error, len(data))
	for i := 0; i < len(data); i++ {
		dataItem := data[i]

		dataBytes, err := json.Marshal(dataItem)
		if err != nil {
			log.SyslogErr("ApproveDotTrans, Marshal dataBytes", "err", err.Error())
			//return nil, err
			continue
		}
		approvedKey := genDBKey(dataItem, mpcprotocol.MpcApprovedDot)
		approvingKey := genDBKey(dataItem, mpcprotocol.MpcApprovingDot)
		approvingKeysKey := []byte(mpcprotocol.MpcApprovingKeysDot)

		retResult[i] = approve(approvedKey, approvingKey, approvingKeysKey, dataBytes)

		log.SyslogInfo("ApproveDotTrans",
			"transactionInfo", dataItem.String(),
			"approvedKey", hexutil.Encode(approvedKey),
			"approvingKey", hexutil.Encode(approvingKey))
	}

	return retResult
}
